﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FinanSoft.Utilities;
using FinanSoft.Entities;
using FinanSoft.BusinessLayer;

namespace FinanSoft.PresentacionSociosNegocios
{
    public partial class frmCrearCuentaAuxiliar : Form
    {
        private int[] _currencyIds;
        private int _editedAccountId;
        private AuxiliarAccount _currentAuxAccount;
        List<int> _accountIds;

        public frmCrearCuentaAuxiliar(int editedAccountId)
        {
            _editedAccountId = editedAccountId;
            InitializeComponent();
            if (_editedAccountId != Constants.INVALID_ID)
                getAuxiliarAccount(_editedAccountId);
            fillParents();
            fillCurrencies();
            fillPayConditions();

            if (_editedAccountId != Constants.INVALID_ID)
                fillInformation();
        }


        #region Métodos para rellenar los campos en pantalla
        /// <summary>
        /// Método que se encarga de llenar el combo de las condiciones de pago
        /// </summary>
        private void fillPayConditions()
        {
            int selectedId = Constants.INVALID_ID;
            // Aqui se  hace la llamada a la función
            List<String> addedConditions = getPayConditions();

            for (int condIndex = 0; condIndex < addedConditions.Count; condIndex++)
            {
                comboCond.Items.Add(addedConditions[condIndex]);
                if (_editedAccountId != Constants.INVALID_ID && addedConditions[condIndex].Equals(_currentAuxAccount.PayCondition))
                    selectedId = condIndex;
            }
            if (selectedId != Constants.INVALID_ID)
                comboCond.SelectedIndex = selectedId;
            else
                comboCond.SelectedIndex = 0;
        }

        /// <summary>
        /// Método que se encarga de rellenar el campo de la moneda
        /// </summary>
        private void fillCurrencies()
        {
            int selectedId = Constants.INVALID_ID;
            List<Currency> addedCurrencies = MoneyManager.GetInstance().GetAddedCurrencies();
            _currencyIds = new int[addedCurrencies.Count + 2];
            for (int currencyIndex = 0; currencyIndex < addedCurrencies.Count; currencyIndex++)
            {
                _currencyIds[currencyIndex] = addedCurrencies[currencyIndex].Id;
                cmbMoneda.Items.Add(addedCurrencies[currencyIndex].Name);
                if (isEditedCurrency(addedCurrencies[currencyIndex].Id))
                    selectedId = currencyIndex;
            }
            Currency sys = MoneyManager.GetInstance().SystemCurrency;
            _currencyIds[_currencyIds.Length - 2] = sys.Id;
            cmbMoneda.Items.Add(sys.Name);
            if (isEditedCurrency(sys.Id))
                selectedId = _currencyIds.Length - 2;
            Currency local = MoneyManager.GetInstance().LocalCurrency;
            _currencyIds[_currencyIds.Length - 1] = local.Id;
            cmbMoneda.Items.Add(local.Name);
            if (selectedId != Constants.INVALID_ID)
                cmbMoneda.SelectedIndex = selectedId;
            else
                cmbMoneda.SelectedIndex = cmbMoneda.Items.Count - 1;
        }

        private bool isEditedCurrency(int currencyId)
        {
            return _editedAccountId != Constants.INVALID_ID && currencyId == AuxiliaryAccountManager.GetInstance().GetAuxiliarAccount(_editedAccountId).AccountCurrency.Id;
        }

        /// <summary>
        /// Método que se encarga de rellenar los textfields a la hora de editar una cuenta
        /// con los datos de la cuenta, así como los radiobuttons, y desactiva los que no pueden
        /// ser cambiados......
        /// </summary>
        private void fillInformation()
        {
            if (_currentAuxAccount != null)
            {
                txtName.Text = _currentAuxAccount.Name;
                txtOwnerName.Text = _currentAuxAccount.OwnerName;
                txtCredit.Text = _currentAuxAccount.LimitedCreditAmount.ToString();
                txtCodSystem.Text = _currentAuxAccount.AccountCode;
                if (_currentAuxAccount.EntryType == Constants.AuxiliarEntryType.person)
                    radPersona.Checked = true;
                else
                    radEmpresa.Checked = true;
                if (_currentAuxAccount.AccountType == Constants.AuxiliarAccountType.client)
                    radCliente.Checked = true;
                else
                    radProveedor.Checked = true;
                txtCodSystem.Enabled = false;
                radCliente.Enabled = false;
                radEmpresa.Enabled = false;
                radPersona.Enabled = false;
                radProveedor.Enabled = false;
                int selectedIndex = _accountIds.IndexOf(_currentAuxAccount.Parent);
                cmbCtaPadre.SelectedIndex = selectedIndex;
            }
            else
            {
                MessageBox.Show("No se encontró la cuenta a editar", MessageConstants.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
                Close();
            }
        }

        /// <summary>
        /// Método que se encarga de llenar la lista de cuentas mayores
        /// </summary>
        private void fillParents()
        {
            _accountIds = new List<int>();
            AccountingCatalog catalog = CatalogManager.GetInstance().GetAccountingCatalog();
            foreach (Account account in catalog.PrincipalAccounts)
                addAccount(account);
            cmbCtaPadre.SelectedIndex = 0;
        }

        private void addAccount(Account account)
        {
            if (!account.IsTitle)
            {
                _accountIds.Add(account.AccountID);
                cmbCtaPadre.Items.Add(account.DisplayName);
            }
            else
                foreach (Account child in account.Children.Values)
                    addAccount(child);
        }

        #endregion

        #region Métodos para validar los campos en pantalla
        /// <summary>
        /// Método que se encarga de recolectar los datos para crear una nueva cuenta auxiliar
        /// </summary>
        private void createAccount()
        {
            if (validateCreateFields())
            {
                AuxiliarAccount newAccount = new AuxiliarAccount();
                newAccount.AccountCurrency = MoneyManager.GetInstance().GetCurrency(_currencyIds[cmbMoneda.SelectedIndex]);
                newAccount.Name = txtName.Text;
                newAccount.OwnerName = txtOwnerName.Text;
                newAccount.AccountCode = txtCodSystem.Text;
                newAccount.LimitedCreditAmount = Convert.ToDouble(txtCredit.Text);
                if (radPersona.Checked == true)
                    newAccount.EntryType = Constants.AuxiliarEntryType.person;
                else
                    newAccount.EntryType = Constants.AuxiliarEntryType.company;
                if (radCliente.Checked == true)
                    newAccount.AccountType = Constants.AuxiliarAccountType.client;
                else
                    newAccount.AccountType = Constants.AuxiliarAccountType.provider;
                newAccount.PayCondition = comboCond.SelectedItem.ToString();
                newAccount.Parent = CatalogManager.GetInstance().GetAccount(_accountIds[cmbCtaPadre.SelectedIndex]).AccountID;
               
                AuxiliaryAccountManager.GetInstance().CreateNewAuxiliarAccount(newAccount);
                if (AuxiliaryAccountManager.GetInstance().IsError)
                    MessageBox.Show(AuxiliaryAccountManager.GetInstance().ErrorMessage, MessageConstants.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
                else
                {
                    MessageBox.Show(MessageConstants.ACCOUNT_INSERTED, MessageConstants.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                    Close();
                }
            }
        }

        /// <summary>
        /// Método que se encarga de recolectar los datos para modificar una cuenta auxiliar
        /// </summary>
        private void editAccount()
        {
            if (validateUpdateFields())
            {
                AuxiliarAccount newAccount = new AuxiliarAccount();
                newAccount.AccountID = _editedAccountId;
                newAccount.AccountCurrency = MoneyManager.GetInstance().GetCurrency(_currencyIds[cmbMoneda.SelectedIndex]);
                newAccount.Name = txtName.Text;
                newAccount.OwnerName = txtOwnerName.Text;
                newAccount.PayCondition = comboCond.SelectedItem.ToString();
                newAccount.Parent = CatalogManager.GetInstance().GetAccount(_accountIds[cmbCtaPadre.SelectedIndex]).AccountID;
                newAccount.LimitedCreditAmount = Convert.ToDouble(txtCredit.Text);
                newAccount.AccountCode = txtCodSystem.Text;
                newAccount.Amount = AuxiliaryAccountManager.GetInstance().GetAuxiliarAccount(_editedAccountId).Amount;
                AuxiliaryAccountManager.GetInstance().ModifyAuxiliarAccount(newAccount);
                if (AuxiliaryAccountManager.GetInstance().IsError)
                    MessageBox.Show(AuxiliaryAccountManager.GetInstance().ErrorMessage, MessageConstants.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
                else
                {
                    MessageBox.Show(MessageConstants.ACCOUNT_UPDATED, MessageConstants.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                    Close();
                }
            }
        }

        /// <summary>
        /// Método que valida los campos a la hora de modificar una cuenta
        /// </summary>
        /// <returns></returns>
        private bool validateUpdateFields()
        {
            if (txtName.Text.Trim().Length == 0 || txtOwnerName.Text.Trim().Length == 0 || txtCredit.Text.Trim().Length == 0)
            {
                MessageBox.Show(MessageConstants.MISSING_FIELDS, MessageConstants.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return false;
            }
            else
                return true;
        }

        /// <summary>
        ///  Método que valida los campos a la hora de crear o modificar una cuenta
        /// </summary>
        /// <returns></returns>
        private bool validateCreateFields()
        {
            if (txtCodSystem.Text.Trim().Length == 0)
            {
                MessageBox.Show(MessageConstants.MISSING_FIELDS, MessageConstants.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return false;
            }
            else if (txtCodSystem.Text.Length > Constants.MAX_ACCOUNT_CODE_CHAR - 1)
            {
                MessageBox.Show(MessageConstants.ACCOUNT_CODE_MUST_BE_15, MessageConstants.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return false;
            }
            else
                return validateUpdateFields();
        }
        #endregion

        #region Métodos que llaman a la capa de business por información o para guardar info
        /// <summary>
        /// Método que busca a la cuenta auxiliar con dicho id
        /// </summary>
        /// <param name="accountId"></param>
        private void getAuxiliarAccount(int accountId)
        {
            /*AuxiliarAccount newa = new AuxiliarAccount();
            newa.AccountCode = "1333";
            newa.AccountID = 10;
            newa.AccountCurrency = MoneyManager.GetInstance().GetCurrency(3);
            newa.AccountType = Constants.AuxiliarAccountType.provider;
            newa.Amount = 0;
            newa.EntryType = Constants.AuxiliarEntryType.person;
            newa.LimitedCreditAmount = 0;
            newa.Name = "prueba4";
            newa.OwnerName = "mono";
            newa.Parent = 95;
            newa.PayCondition = "A los 15";*/
            // Aquí llamo a la función
            _currentAuxAccount = AuxiliaryAccountManager.GetInstance().GetAuxiliarAccount(accountId);
        }

        /// <summary>
        /// Método que se encarga de solicitar la lista de condiciones de pago
        /// </summary>
        private List<String> getPayConditions()
        {
            // aqui tengo que llamar la
            return AuxiliaryAccountManager.GetInstance().GetConditionsList();
        }
        #endregion

        #region Métodos de eventos en pantalla
        /// <summary>
        /// Evento: Se encarga de recolectar los datos de pantalla y mandarlos a guardar al sistema
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGuardar_Click(object sender, EventArgs e)
        {
            if (_editedAccountId == Constants.INVALID_ID)
                createAccount();
            else
                editAccount();
                
        }

        /// <summary>
        /// Evento: Si la cuenta es de tipo proveedor no se ocupa un crédito límite
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void radProveedor_CheckedChanged(object sender, EventArgs e)
        {
            txtCredit.Text = "0";
            txtCredit.Enabled = false;
        }

        /// <summary>
        /// Evento: Si la cuenta es de tipo cliente se ocupa un crédito límite
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void radCliente_CheckedChanged(object sender, EventArgs e)
        {
            txtCredit.Text = "";
            txtCredit.Enabled = true;
        }

        /// <summary>
        /// Evento de cerrar ventana de diálogo
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCerrar_Click(object sender, EventArgs e)
        {
            Close();
        }
        #endregion

        private void txtCredit_KeyPress(object sender, KeyPressEventArgs e)
        {
            const char Delete = (char)8;
            e.Handled = !Char.IsDigit(e.KeyChar) && e.KeyChar != Delete;
        }

    }
}
